home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 402_01 / cforms-2.2 / src / cflib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-20  |  40.3 KB  |  1,817 lines

  1. /*****************************************************************************
  2.  *
  3.  *        C F O R M S . C
  4.  *        ---------------
  5.  *
  6.  * Description:
  7.  *
  8.  * Included functions:
  9.  *
  10.  *        Misc functions
  11.  *        --------------
  12.  *    cforms_end    - Stop CForms
  13.  *    cforms_init    - Initiate CForms
  14.  *    cforms_refresh    - Refresh the CForms screen.
  15.  *    cforms_system    - Call the operating system
  16.  *
  17.  *        Picture functions
  18.  *        -----------------
  19.  *    pic_call    - Call picture
  20.  *    pic_clear    - Clear all fields for picture
  21.  *    pic_leave    - Leave current picture
  22.  *    picture        - Get picture with name
  23.  *
  24.  *        Field functions
  25.  *        ---------------
  26.  *    field        - Get field with name
  27.  *    fld_isempty    - Check if field is empty
  28.  *    fld_first    - Find first field of picture
  29.  *    fld_next    - Find next field for picture
  30.  *    fld_previous    - Find previous field for picture
  31.  *    fld_left    - Find left field
  32.  *    fld_right    - Find right field
  33.  *    fld_up        - Find field above current
  34.  *    fld_down    - Find field below current
  35.  *    fld_set        - Set value for field
  36.  *    fld_nset    - Set value for field but max n chars
  37.  *    fld_get        - Get value of field
  38.  *    fld_len        - Return length of field
  39.  *    fld_name    - Return name of field
  40.  *    fld_ismodified    - Return true if field has been modified since fld_set
  41.  *    fld_sattr    - Set attributes for field.
  42.  *    fld_cattr    - Clear attributes for field.
  43.  *    fld_touch    - Make field not modified
  44.  *
  45.  *        General functions
  46.  *        -----------------
  47.  *    message        - Give message (line 24)
  48.  *    strequ        - Compqare two strings, but case insensitive 
  49.  *
  50.  *        Local functions
  51.  *        ---------------
  52.  *    hdl_field    - This is the head function for cforms
  53.  *    getraw        - Get raw key
  54.  *    draw_picture    - Draw picture with fields
  55.  *    draw_field    - Draw field.
  56.  *    check_int    - Checkfunction for integer fields
  57.  *    check_alnum    -     -''-          alphanumeric fields
  58.  *    check_char    -     -''-          character fields
  59.  *    adjust_right    - Adjust string to right
  60.  *    generate_event    - Raise event and call event functions and handle
  61.  *              if field is moved.
  62.  *    raw_event    - Raise event and call event functions
  63.  *
  64.  * Global variables:
  65.  *    none
  66.  *
  67.  * Revision:
  68.  *    Ver    Date    By        Reason
  69.  *    ---    ----    --        ------
  70.  *    1.00    900629    Lars Berntzon    Created
  71.  *
  72.  ****************************************************************************/ 
  73.  
  74. #ifndef lint
  75. static volatile char sccs_id[] = "@(#) cflib.c,v 1.23 1993/07/21 01:15:18 lasse Exp";
  76. #endif
  77.  
  78. #include "config.h"
  79. #include "cforms.h"
  80.  
  81. #define KEY_CTRL(c)    (toupper(c) - 'A' + 1)
  82.  
  83. #ifndef ACS_ULCORNER
  84. #define ACS_ULCORNER    '+'
  85. #endif
  86. #ifndef ACS_LLCORNER
  87. #define ACS_LLCORNER    '+'
  88. #endif
  89. #ifndef ACS_URCORNER
  90. #define ACS_URCORNER    '+'
  91. #endif
  92. #ifndef ACS_LRCORNER
  93. #define ACS_LRCORNER    '+'
  94. #endif
  95. #ifndef ACS_HLINE
  96. #define ACS_HLINE '-'
  97. #endif
  98. #ifndef ACS_VLINE
  99. #define ACS_VLINE '|'
  100. #endif
  101.  
  102.  
  103.     /* G l o b a l   v a r i a b l e s */
  104.  
  105. struct global _cf_globals;    /* Current field and picture        */
  106.  
  107.     /* L o c a l   v a r i a b l e s */
  108.  
  109. #ifdef SIGNAL_INT
  110. static int sigcatch(int sig);
  111. #else
  112. static void sigcatch(int sig);
  113. #endif
  114. static int _message(const char *fmt, va_list arg);
  115. static int check_int(int *ch, char *txt, int *pos, int len);
  116. static int check_alnum(int *ch, char *txt, int *pos, int len);
  117. static int check_char(int *ch, char *txt, int *pos, int len);
  118. static int draw_picture(struct picture *pic);
  119. static void draw_field(struct field *fld);
  120. static void move_to_field(struct field *fld);
  121. static int hdl_field(struct field *fld);
  122. static int adjust_right(char *txt, int len);
  123. static void debug(char *fmt, ...);
  124. static int generate_event(int ev_type, int ev_spec, int ev_code);
  125. static int raw_event(int ev_type, int ev_spec, int ev_code);
  126.  
  127. static struct picture *pstack[200];
  128. static int pstackp = 0;
  129. static int cforms_inited = FALSE;
  130.  
  131.  
  132. /******************************************************************************
  133.  *
  134.  *        C F O R M S _ I N I T
  135.  *        ---------------------
  136.  * Description:
  137.  *    Initialize cforms. (currently only initscr).
  138.  *
  139.  *****************************************************************************/
  140. int
  141. cforms_init(void)
  142. {
  143.     int pic, fld;
  144.     int m;
  145.  
  146.     cforms_inited = TRUE;
  147.  
  148.     signal(SIGINT, sigcatch);
  149.     
  150.     if (initscr() == NULL) {
  151.         return FAIL;
  152.     }
  153.     keypad(stdscr,TRUE);
  154.  
  155.     /*
  156.      * Save picture pointer for every field.
  157.      */
  158.     for(m = 0; _cf_modules[m] != NULL; m++)
  159.     {
  160.     for(pic = 0; pic < _cf_modules[m]->n_pictures; pic++)
  161.     {
  162.         for(fld = 0; fld < _cf_modules[m]->picture[pic].n_fields; fld++)
  163.         {
  164.         _cf_modules[m]->picture[pic].field[fld].picture =
  165.             &_cf_modules[m]->picture[pic];
  166.         }
  167.     }
  168.     }
  169.  
  170.     raw();
  171.     noecho();
  172.  
  173.     /*
  174.      * Set up some default keys for field editing.
  175.      */
  176.     _cf_globals.bs = '\b';
  177.     _cf_globals.del1 = 'D' & 0x1F;
  178.     _cf_globals.del2 = 127;
  179.     _cf_globals.kill = 'K' & 0x1F;
  180.     _cf_globals.clear = 'U' & 0x1F;
  181.  
  182.     return OK;
  183. }
  184.  
  185. /******************************************************************************
  186.  *
  187.  *        C F O R M S _ E N D
  188.  *        -------------------
  189.  *
  190.  * Description:
  191.  *    Turns off cforms.
  192.  *
  193.  *****************************************************************************/
  194. int
  195. cforms_end(void)
  196. {
  197.     cforms_inited = FALSE;
  198.     move(23, 1);
  199.     refresh();
  200.     endwin();
  201.     
  202.     return OK;
  203. }
  204.  
  205. /******************************************************************************
  206.  *
  207.  *        C F O R M S _ R E F R E S H
  208.  *        ---------------------------
  209.  *
  210.  * Description:
  211.  *    Refresh the CForms application window.
  212.  *
  213.  *****************************************************************************/
  214. void
  215. cforms_refresh(void)
  216. {
  217.     int i;
  218.  
  219.     clear();
  220.     for(i = 0; i < pstackp; i++) {
  221.     debug("drawing picture %d", i);
  222.     draw_picture(pstack[i]);
  223.     }
  224.     generate_event(EVENT_REFRESH, 0, 0);
  225. }
  226.  
  227. /*******************************************************************************
  228.  *
  229.  *        C F O R M S _ S Y S T E M
  230.  *        -------------------------
  231.  *
  232.  *
  233.  * Description:
  234.  *    Execute an operating system command from CForms without destroying
  235.  *    the screen.
  236.  *    
  237.  *
  238.  * Input:
  239.  *    command        - OS command to execute.
  240.  *
  241.  * Return:
  242.  *    Integer return value from system command.
  243.  *
  244.  ******************************************************************************/
  245. int
  246. cforms_system(const char *command, const char *prompt)
  247. {
  248.     int result;
  249.     char ch;
  250.   
  251.     if (command == NULL) {
  252.     return 0;
  253.     }
  254.     /*
  255.      * Clean the picture.
  256.      */
  257.     clear();
  258.     refresh();
  259.     endwin();
  260.  
  261.     putenv("IFS= \t\n");    /* Make system() a bit more secure    */
  262.     result = system(command);
  263.  
  264.     if (prompt != NULL)
  265.     {
  266.     write(1, prompt, strlen(prompt));
  267.     while(read(0, &ch, 1) == 1 && ch != '\n')
  268.         ;
  269.     }
  270.  
  271.     initscr();
  272.     keypad(stdscr,TRUE);
  273.  
  274.     cforms_refresh();
  275.  
  276.     return result;
  277. }
  278.  
  279.  
  280. /*******************************************************************************
  281.  *
  282.  *        P I C _ C A L L
  283.  *        ---------------
  284.  *
  285.  *
  286.  * Description:
  287.  *    This is the entry point for application into CForms
  288.  *
  289.  * Input:
  290.  *    pic        - Picture to call
  291.  *    field_name    - Name of field to start at, (NULL means first field).
  292.  *
  293.  * Global:
  294.  *    _cf_globals.picture    - Is set up to point to this picture
  295.  *
  296.  ******************************************************************************/
  297. int
  298. pic_call(struct picture *pic, const char *field_name)
  299. {
  300.     struct global old_globals = _cf_globals;
  301.     
  302.     if (cforms_inited == FALSE) {
  303.     fprintf(stderr, "** CForms not initialized **\n");
  304.     return FAIL;
  305.     }
  306.  
  307.     if (pic == NULL) return FAIL;
  308.     
  309.     _cf_globals.picture = pic;
  310.     _cf_globals.field = NULL;
  311.  
  312.     /*
  313.      * Keep track of how pictures are stacked in case of a refresh
  314.      * is orderded from keyboard.
  315.      */
  316.     pstack[pstackp++] = pic;
  317.     
  318.     /*
  319.      * Paint the new picture.
  320.      */
  321.     draw_picture(pic);
  322.  
  323.     /*
  324.      * The event draw is special in that it is only valid for pictures.
  325.      */
  326.     generate_event(EVENT_DRAW, 0, 0);
  327.      
  328.     /*
  329.      * If field is still not set in EVENT_DRAW, go to proper one.
  330.      */
  331.     if (_cf_globals.field == NULL) {
  332.     if (field_name) move_to_field(field(field_name));
  333.     else move_to_field(fld_first());
  334.     }
  335.     
  336.     /*
  337.      * Make sure there really exists a field to move to in
  338.      * picture.
  339.      */
  340.     if (_cf_globals.field != NULL)
  341.     {
  342.     while(_cf_globals.leave_picture == FALSE)
  343.     {
  344.         hdl_field(_cf_globals.field);
  345.     } 
  346.     generate_event(EVENT_EXIT, 0, 0);
  347.     }
  348.  
  349.     /*
  350.      * Redraw the picture picture that was active before
  351.      * this one was called and make that old one active again.
  352.      */
  353.     _cf_globals = old_globals;
  354.  
  355.     if (_cf_globals.picture)
  356.     {
  357.     draw_picture(_cf_globals.picture);
  358.     generate_event(EVENT_REFRESH, 0, 0);
  359.     }
  360.     pstackp--;
  361.     return OK;
  362. }
  363.  
  364.  
  365. /*******************************************************************************
  366.  *
  367.  *        P I C T U R E
  368.  *        -------------
  369.  *
  370.  * Description:
  371.  *    Finds a picture with name as described by arguments in printf format.
  372.  *
  373.  ******************************************************************************/
  374. struct picture *
  375. picture(const char *fmt, ...)
  376. {
  377.     static char pic_name[100];
  378.     va_list arg;
  379.     int i;
  380.     int m;
  381.     
  382.     va_start(arg, fmt);
  383.     vsprintf(pic_name, fmt, arg);
  384.     va_end(arg);
  385.  
  386.     /*
  387.      * Loop through all modules and their pictures
  388.      * to find name.
  389.      */
  390.     for(m = 0; _cf_modules[m] != 0; m++)
  391.     {
  392.     for(i = 0; i < _cf_modules[m]->n_pictures; i++)
  393.     {
  394.         if (strequ(pic_name, _cf_modules[m]->picture[i].name) == 0)
  395.         {
  396.         return &_cf_modules[m]->picture[i];
  397.         }
  398.     }
  399.     }
  400.     return NULL;
  401. }
  402.  
  403.  
  404. /*******************************************************************************
  405.  *
  406.  *        P I C _ L E A V E
  407.  *        -----------------
  408.  *
  409.  * Description:
  410.  *    Leave picture uppon exit of current event.
  411.  *
  412.  ******************************************************************************/
  413. int
  414. pic_leave(void)
  415. {
  416.     _cf_globals.leave_picture = TRUE;
  417.     return OK;
  418. }
  419.  
  420.  
  421. /*******************************************************************************
  422.  *
  423.  *        P I C _ C L E A R
  424.  *        -----------------
  425.  *
  426.  * Description:
  427.  *    Clear all field of picture 'pic'.
  428.  *
  429.  ******************************************************************************/
  430. int
  431. pic_clear(struct picture *pic)
  432. {
  433.     int i, n;
  434.     
  435.     if (pic == NULL) pic = _cf_globals.picture;
  436.     if (pic == NULL) return FAIL;
  437.     
  438.     for(i = 0; i < pic->n_fields; i++) {
  439.     pic->field[i].data[0] = 0;
  440.     }
  441.  
  442.     if (_cf_globals.picture == pic) {
  443.     for(i = 0; i < pic->n_fields; i++) {
  444.         move(pic->field[i].pos.y + pic->y, pic->field[i].pos.x + pic->x);
  445.         for(n = 0; n < pic->field[i].len; n++) {
  446.             addch(' ');
  447.         }
  448.     }
  449.     }
  450.     return OK;
  451. }
  452.  
  453.  
  454. /*******************************************************************************
  455.  *
  456.  *        H D L _ F I E L D
  457.  *        -----------------
  458.  *
  459.  * Description:
  460.  *    Handles the intput of one field. When ever a event is generated
  461.  *    this function returns to pic_call which should handle the results
  462.  *    of this event. Also when a field is moved this function will return.
  463.  *
  464.  * Arguments:
  465.  *    fld    - Pointer to field to handle.
  466.  *
  467.  ******************************************************************************/
  468. static int
  469. hdl_field(struct field *fld)
  470. {
  471.     int (*check_p)();
  472.     int x, y, ch, i, pos = 0;
  473.     struct field *tmp_fld;
  474.     
  475.     move((y = fld->pos.y) + fld->picture->y,
  476.      (x = fld->pos.x) + fld->picture->x);
  477.     
  478.     /*
  479.      * Setup which function to handle key input to field.
  480.      */
  481.     switch(fld->type & FLD_TYPE)
  482.     {
  483.     case FLD_CHAR:
  484.         check_p = check_char;
  485.         break;
  486.         
  487.     case FLD_ALNUM:
  488.         check_p = check_alnum;
  489.         break;
  490.  
  491.     case FLD_INT:
  492.         check_p = check_int;
  493.         break;
  494.         
  495.     default:
  496.         message("Illegal field type, probably a bug in CForms");
  497.     }
  498.     
  499.     /*
  500.      * Pad field with spaces after null.
  501.      */
  502.     i = strlen(fld->data);
  503.     memset(fld->data + i, ' ', fld->len - i);
  504.     fld->data[fld->len] = 0;
  505.     
  506.     /*
  507.      * Handle keys pressed by user.
  508.      */
  509.     while (refresh(), (ch = getch()) != EOF)
  510.     {
  511.     message_nr("");
  512.     
  513.     /*
  514.      * Second try to generated an event for the key pressed.
  515.      */
  516.     if (generate_event(EVENT_KEY, KEY_ANY, ch))
  517.     {
  518.         break;
  519.     }
  520.     /*
  521.      * Second try to generated an event for the key pressed.
  522.      */
  523.     else if (generate_event(EVENT_KEY, ch, ch))
  524.     {
  525.         break;
  526.     }
  527.     /*
  528.      * If CTRL-W then do refresh.
  529.      */
  530.     else if (ch == KEY_CTRL('w'))
  531.     {
  532.         cforms_refresh();
  533.     }
  534.     /*
  535.      * If newline adjust the field if it should be.
  536.      */
  537.     else if (ch == '\n')
  538.     {
  539.         if (fld->type & FLD_RIGHT)
  540.         {
  541.             adjust_right(fld->data, fld->len);
  542.         }
  543.     }
  544.     /*
  545.      * Move one pos left.
  546.      */
  547.       else if (ch == KEY_LEFT)
  548.     {
  549.          if (pos <= 0 || (fld->flags & FLD_PROTECTED))
  550.         {
  551.              if (generate_event(EVENT_PREVIOUS, 0, 0))
  552.         {
  553.             break;
  554.         }
  555.              else if (tmp_fld = fld_left(_cf_globals.field))
  556.         {
  557.                  move_to_field(tmp_fld);
  558.                  break;
  559.              }
  560.              else message("Can't move left");
  561.          }
  562.          else {
  563.              pos--;
  564.         }
  565.     }
  566.     /*
  567.      * Move one pos right.
  568.      */
  569.     else if (ch == KEY_RIGHT)
  570.     {
  571.         if (pos >= fld->len - 1 || (fld->flags & FLD_PROTECTED))
  572.         {
  573.             if (generate_event(EVENT_NEXT, 0, 0))
  574.         {
  575.             break;
  576.         }
  577.             else if (tmp_fld = fld_right(_cf_globals.field))
  578.         {
  579.                 move_to_field(tmp_fld);
  580.                 break;
  581.             }
  582.             else message("Can't move right");
  583.         }
  584.         else
  585.         {
  586.             pos++;
  587.         }
  588.     }
  589.     /*
  590.      * From here on data in the field is actually modified,
  591.      * unless if protected in case it is not allowed.
  592.      */
  593.     else if (fld->flags & FLD_PROTECTED)
  594.     {
  595.         message("No input allowed");
  596.     }
  597.     /*
  598.      * Backspace.
  599.      */
  600.     else if (ch == _cf_globals.bs)
  601.     {
  602.         if (pos > 0) {
  603.         for(i = pos; i < fld->len; i++)
  604.         {
  605.             fld->data[i - 1] = fld->data[i];
  606.         }
  607.         fld->data[i - 1] = ' ';
  608.         pos--;
  609.         }
  610.         fld->modified = 1;
  611.     }
  612.     /*
  613.      * Check if CTRL-D or delete.
  614.      */
  615.     else if (ch == _cf_globals.del1 || ch == _cf_globals.del2)
  616.     {
  617.         for(i = pos + 1; i < fld->len; i++)
  618.         {
  619.         fld->data[i - 1] = fld->data[i];
  620.         }
  621.         fld->data[i - 1] = ' ';
  622.         
  623.         fld->modified = 1;
  624.     }
  625.     /*
  626.      * CTRL-K clears the rest of the field.
  627.      */
  628.     else if (ch == _cf_globals.kill)
  629.     {
  630.         for(i = pos; i < fld->len; i++)
  631.         {
  632.         fld->data[i] = ' ';
  633.         }
  634.         
  635.         fld->modified = 1;
  636.     }
  637.     /*
  638.      * CTRL-U clears the whole field.
  639.      */
  640.     else if (ch == _cf_globals.clear)
  641.     {
  642.         pos = 0;
  643.         for(i = pos; i < fld->len; i++)
  644.         {
  645.         fld->data[i] = ' ';
  646.         }
  647.         
  648.         fld->modified = 1;
  649.     }
  650.     /*
  651.      * Control characters ?, no no.
  652.      */
  653.     else if (!isprint(ch))
  654.     {
  655.         message("Unknown key (%d)", ch);
  656.     }
  657.     /*
  658.      *  This is actually where data gets written into the field.
  659.      */
  660.     else if (check_p(&ch, fld->data, &pos, fld->len))
  661.     {
  662.         if (fld->flags & FLD_UPPERCASE) ch = toupper(ch);
  663.         for(i = fld->len - 1; i > pos; i--)
  664.         {
  665.         fld->data[i] = fld->data[i - 1];
  666.         }
  667.         fld->data[pos] = ch;
  668.         if (pos < fld->len - 1) pos++;
  669.         fld->modified = 1;
  670.     }
  671.  
  672.     draw_field(fld);
  673.     move(y + fld->picture->y, x + fld->picture->x + pos);
  674.     }
  675.  
  676.     if (fld->type & FLD_RIGHT)
  677.     {
  678.     adjust_right(fld->data, fld->len);
  679.     }
  680.     return OK;
  681. }
  682.  
  683.  
  684. /*******************************************************************************
  685.  *
  686.  *        M E S S A G E, M E S S A G E _ N R
  687.  *        ----------------------------------
  688.  *
  689.  * Description:
  690.  *    Give message on bottom screen line. Work the same way as printf.
  691.  *    message_nr works the same as message but gives no refresh.
  692.  *
  693.  ******************************************************************************/
  694. int
  695. message(const char *fmt, ...)
  696. {
  697.     va_list arg;
  698.     va_start(arg, fmt);
  699.     _message(fmt, arg);
  700.     va_end(arg);
  701.     refresh();
  702.     return OK;
  703. }
  704.  
  705. int
  706. message_nr(const char *fmt, ...)
  707. {
  708.     va_list arg;
  709.     va_start(arg, fmt);
  710.     _message(fmt, arg);
  711.     va_end(arg);
  712.     return OK;
  713. }
  714.  
  715. static int
  716. _message(const char *fmt, va_list arg)
  717. {
  718.     static char msg_str[160];
  719.     char tmp_str[160];
  720.     int x, y;
  721.  
  722.     getyx(stdscr, y, x);
  723.     
  724.     move(23, 1);
  725.     if (fmt != NULL) {
  726.     vsprintf(tmp_str, fmt, arg);
  727.     sprintf(msg_str, "%-50.50s", tmp_str);
  728.     }
  729.     addstr(msg_str);
  730.     move(y, x);
  731.     return OK;
  732. }
  733.  
  734.  
  735. /*******************************************************************************
  736.  *
  737.  *        C H E C K *
  738.  *        -----------
  739.  *
  740.  * Description:
  741.  *    Various check functions depending of type of field.
  742.  *    If function returnes TRUE, the char ch is put into field.
  743.  *
  744.  ******************************************************************************/
  745. static int
  746. check_int(int *ch, char *txt, int *pos, int len)
  747. {
  748.     int i;
  749.     if (isdigit(*ch)) {
  750.     return TRUE;
  751.     }
  752.  
  753.     if (isspace(*ch)) {
  754.     for(i = 0; i < *pos; i++) {
  755.         if (!isspace(txt[i])) {
  756.         message("No space in middle of value");
  757.         return FALSE;
  758.         }
  759.     }
  760.     return TRUE;
  761.     }
  762.     message ("Must be digit");
  763.     return FALSE;
  764. }
  765.  
  766. static int
  767. check_alnum(int *ch, char *txt, int *pos, int len)
  768. {
  769.     if (isalnum(*ch) || isspace(*ch)) return TRUE;
  770.     message("Must be alphanumeric");
  771.     return FALSE;
  772. }
  773.  
  774. static int
  775. check_char(int *ch, char *txt, int *pos, int len)
  776. {
  777.     if (isprint(*ch)) return TRUE;
  778.     message("Must be printable");
  779.     return FALSE;
  780. }
  781.  
  782.  
  783. /*******************************************************************************
  784.  *
  785.  *        A D J U S T _ R I G H T
  786.  *        -----------------------
  787.  *
  788.  * Description:
  789.  *    Adjust a text to the right
  790.  *
  791.  ******************************************************************************/
  792. static int
  793. adjust_right(char *txt, int len)
  794. {
  795.     int last_space = len - 1;
  796.     
  797.     while(isspace(txt[last_space]) && last_space >= 0)
  798.     last_space--;
  799.     last_space++;
  800.     memcpy(txt + len - last_space, txt, last_space);
  801.     memset(txt, ' ', len - last_space);
  802.  
  803.     return OK;
  804. }
  805.  
  806.  
  807. /*******************************************************************************
  808.  *
  809.  *        G E N E R A T E _ E V E N T
  810.  *        ---------------------------
  811.  *
  812.  * Description:
  813.  *    Calls raw_event to make the event execute. After that it checks if
  814.  *    field has been moved in case move_to_field is called.
  815.  *
  816.  * Input:
  817.  *    ev_type        - Event type, ex. EVENT_KEY, EVENT_ENTRY.
  818.  *    ev_spec        - Specified for type.
  819.  *    ev_code        - Code of event (not for all types), ex KEY_UP.
  820.  *
  821.  * Return:
  822.  *    Boolean, TRUE if event code was found and called. Events are not
  823.  *    called for 'event forget' statements (function = NULL).
  824.  *
  825.  ******************************************************************************/
  826. static int
  827. generate_event(int ev_type, int ev_spec, int ev_code)
  828. {
  829.     if (raw_event(ev_type, ev_spec, ev_code) == FALSE)
  830.     {
  831.     return FALSE;
  832.     }
  833.  
  834.     if (_cf_globals.move_field != NULL)
  835.     {
  836.     move_to_field(_cf_globals.move_field);
  837.     }
  838.  
  839.     return TRUE;
  840. }
  841.  
  842.  
  843. /*******************************************************************************
  844.  *
  845.  *        R A W _ E V E N T
  846.  *        -----------------
  847.  *
  848.  * Description:
  849.  *    Generate a event of type and with code, and calls first function
  850.  *    for field or picture that should respond to the event.
  851.  *
  852.  * Input:
  853.  *    ev_type        - Event type, ex. EVENT_KEY, EVENT_ENTRY.
  854.  *    ev_spec        - Event specifier.
  855.  *    ev_code        - Code of event (not for all types), ex KEY_UP.
  856.  *
  857.  * Return:
  858.  *    Boolean, TRUE if event code was found and called. Events are not
  859.  *    called for 'event forget' statements (function = NULL).
  860.  *
  861.  ******************************************************************************/
  862. int
  863. raw_event(int ev_type, int ev_spec, int ev_code)
  864. {
  865.     int i, m;
  866.     
  867.     /*
  868.      * Check if field has handler for event, exept for DRAW
  869.      * events that is only sent to picture and module event handlers.
  870.      */
  871.     if (ev_type != EVENT_DRAW)
  872.     {
  873.     for(i = 0; _cf_globals.field && i < _cf_globals.field->n_events; i++) {
  874.         if (_cf_globals.field->event[i].type == ev_type &&
  875.         _cf_globals.field->event[i].code == ev_spec) {
  876.             if (_cf_globals.field->event[i].func == NULL)
  877.             {
  878.             return FALSE;
  879.             }
  880.             (*_cf_globals.field->event[i].func)(ev_code);
  881.             return TRUE;
  882.         }
  883.     }
  884.     }
  885.  
  886.     /*
  887.      * The field did not have a handler for the event, lets check if
  888.      * the picture has.
  889.      */
  890.     for(i = 0; _cf_globals.picture && i < _cf_globals.picture->n_events; i++) {
  891.         if (_cf_globals.picture->event[i].type == ev_type &&
  892.             _cf_globals.picture->event[i].code == ev_spec) {
  893.                 if (_cf_globals.picture->event[i].func == NULL) {
  894.                     return FALSE;
  895.                 }
  896.                 (*_cf_globals.picture->event[i].func)(ev_code);
  897.                 return TRUE;
  898.         }
  899.     }
  900.  
  901.     /*
  902.      * The picture did not have a handler for the event, lets check if
  903.      * the module has.
  904.      */
  905.     for(i = 0;  i < _cf_globals.picture->module->n_events; i++) {
  906.         if (_cf_globals.picture->module->event[i].type == ev_type &&
  907.             _cf_globals.picture->module->event[i].code == ev_spec) {
  908.                 if (_cf_globals.picture->module->event[i].func == NULL) {
  909.                     return FALSE;
  910.                 }
  911.                 (*_cf_globals.picture->module->event[i].func)(ev_code);
  912.                 return TRUE;
  913.         }
  914.     }
  915.  
  916.     /*
  917.      * This module did not have a handler for the event, lets check if
  918.      * there is a global event handler.
  919.      */
  920.     for(m = 0; _cf_modules[m] != 0; m++)
  921.     {
  922.     for(i = 0; i < _cf_modules[m]->n_events; i++)
  923.     {
  924.         if (_cf_modules[m]->event[i].global != 0 &&
  925.             _cf_modules[m]->event[i].type == ev_type &&
  926.         _cf_modules[m]->event[i].code == ev_spec) {
  927.             if (_cf_modules[m]->event[i].func == NULL) {
  928.             return FALSE;
  929.             }
  930.             (*_cf_modules[m]->event[i].func)(ev_code);
  931.             return TRUE;
  932.         }
  933.     }
  934.     }
  935.  
  936.     /*
  937.      * No, no event handlers existed for this type of event.
  938.      */
  939.  
  940.     return FALSE;
  941. }
  942.  
  943.  
  944. /*******************************************************************************
  945.  *
  946.  *        F L D _ M O V E
  947.  *        ---------------
  948.  *
  949.  * Description:
  950.  *    Move to field
  951.  *
  952.  * Input:
  953.  *    fld    - Field to move to.
  954.  *
  955.  * Return:
  956.  *    field moved to (or current if forbidden field).
  957.  *
  958.  ******************************************************************************/
  959. struct field *
  960. fld_move(struct field *fld)
  961. {
  962.     if (fld == NULL) fld = _cf_globals.field;
  963.     if (fld->flags & FLD_FORBIDDEN) return _cf_globals.field;
  964.  
  965.     _cf_globals.move_field = fld;
  966.  
  967.     return _cf_globals.move_field;
  968. }
  969.  
  970.  
  971. /*******************************************************************************
  972.  *
  973.  *        F L D _ G E T
  974.  *        -------------
  975.  *
  976.  * Description:
  977.  *    Return text in field.
  978.  *
  979.  ******************************************************************************/
  980. const char *
  981. fld_get(const struct field *fld)
  982. {
  983.     if (fld == NULL) fld = _cf_globals.field;
  984.     if (fld) return fld->data;
  985.  
  986.     return "";
  987. }
  988.  
  989. /*******************************************************************************
  990.  *
  991.  *        F L D _ G E T _ T R I M M E D
  992.  *        -----------------------------
  993.  *
  994.  * Description:
  995.  *    Return text in field but with trimmed blanks at beginning and end.
  996.  *
  997.  ******************************************************************************/
  998. char *
  999. fld_get_trimmed(const struct field *fld)
  1000. {
  1001.     static char txt[1024];
  1002.     char *p;
  1003.     if (fld == NULL) fld = _cf_globals.field;
  1004.  
  1005.     if (fld && fld->data)
  1006.     {
  1007.     for(p = fld->data; isspace(*p); p++)
  1008.         ;
  1009.     strcpy(txt, p);
  1010.     for (p = txt + strlen(txt) - 1; isspace(*p) && p >= txt; p--)
  1011.         ;
  1012.     *(p + 1) = 0;
  1013.     }
  1014.     else {
  1015.     txt[0] = 0;
  1016.     }
  1017.  
  1018.     return txt;
  1019. }
  1020.  
  1021.  
  1022.  
  1023. /*******************************************************************************
  1024.  *
  1025.  *        F L D _ S E T
  1026.  *        -------------
  1027.  *
  1028.  * Description:
  1029.  *    Set value for field.
  1030.  *
  1031.  ******************************************************************************/
  1032. int
  1033. fld_set(struct field *fld, const char *data)
  1034. {
  1035.     int i;
  1036.     
  1037.     if (fld == NULL) fld = _cf_globals.field;
  1038.     if (fld == NULL) return FAIL;
  1039.  
  1040.     memset(fld->data, ' ', fld->len);
  1041.     i = strlen(data);
  1042.     if (i > fld->len) i = fld->len;
  1043.     strncpy(fld->data, data, i);
  1044.     fld->modified = 0;
  1045.     
  1046.     if (fld->picture == _cf_globals.picture) {
  1047.     draw_field(fld);
  1048.     refresh();
  1049.     }
  1050.  
  1051.     return OK;
  1052. }
  1053.  
  1054.  
  1055. /*******************************************************************************
  1056.  *
  1057.  *        F L D _ N S E T
  1058.  *        ---------------
  1059.  *
  1060.  * Description:
  1061.  *    Copy at most 'n' chars from input and set field to that.
  1062.  *
  1063.  ******************************************************************************/
  1064. int
  1065. fld_nset(struct field *fld, const char *data, int n)
  1066. {
  1067.     char tmpstr[200];
  1068.     strncpy(tmpstr, data, n);
  1069.     tmpstr[n] = 0;
  1070.     return fld_set(fld, tmpstr);
  1071. }
  1072.  
  1073.  
  1074. /*******************************************************************************
  1075.  *
  1076.  *        F L D _ L E N
  1077.  *        -------------
  1078.  *
  1079.  * Description:
  1080.  *    Return length of field.
  1081.  *
  1082.  ******************************************************************************/
  1083. int
  1084. fld_len(const struct field *fld)
  1085. {
  1086.     if (fld == NULL) fld = _cf_globals.field;
  1087.     if (fld == NULL) return 0;
  1088.     return fld->len;
  1089. }
  1090. /*******************************************************************************
  1091.  *
  1092.  *        F L D _ N A M E
  1093.  *        ---------------
  1094.  *
  1095.  * Description:
  1096.  *    Return name of field.
  1097.  *
  1098.  ******************************************************************************/
  1099. const char *
  1100. fld_name(const struct field *fld)
  1101. {
  1102.     if (fld == NULL) fld = _cf_globals.field;
  1103.     if (fld == NULL) return 0;
  1104.     return fld->name;
  1105. }
  1106.  
  1107. /*******************************************************************************
  1108.  *
  1109.  *        F L D _ I S M O D I F I E D
  1110.  *        ---------------------------
  1111.  *
  1112.  * Description:
  1113.  *    Return TRUE if field has been modified since last fld_set.
  1114.  *
  1115.  ******************************************************************************/
  1116. int
  1117. fld_ismodified(const struct field *fld)
  1118. {
  1119.     if (fld == NULL) fld = _cf_globals.field;
  1120.     if (fld == NULL) return 0;
  1121.     return fld->modified;
  1122. }
  1123.  
  1124. /*******************************************************************************
  1125.  *
  1126.  *        F L D _ S A T T R
  1127.  *        -----------------
  1128.  *
  1129.  * Description:
  1130.  *    Set attributes for field.
  1131.  *
  1132.  * Arguments:
  1133.  *    attr    - Bitmask of attributes to add to field.
  1134.  *
  1135.  * Return none
  1136.  *
  1137.  ******************************************************************************/
  1138. void
  1139. fld_sattr(struct field *fld, unsigned long attr)
  1140. {
  1141.     if (fld == NULL) fld = _cf_globals.field;
  1142.     if (fld == NULL) return;
  1143.     fld->flags |= attr;
  1144.     if (fld->picture == _cf_globals.picture) {
  1145.     draw_field(fld);
  1146.     refresh();
  1147.     }
  1148. }
  1149.  
  1150. /*******************************************************************************
  1151.  *
  1152.  *        F L D _ C A T T R
  1153.  *        -----------------
  1154.  *
  1155.  * Description:
  1156.  *    Clear attributes for field.
  1157.  *
  1158.  * Arguments:
  1159.  *    attr    - Bitmask of attributes to clear from field.
  1160.  *
  1161.  * Return none
  1162.  *
  1163.  ******************************************************************************/
  1164. void
  1165. fld_cattr(struct field *fld, unsigned long attr)
  1166. {
  1167.     if (fld == NULL) fld = _cf_globals.field;
  1168.     if (fld == NULL) return;
  1169.     fld->flags &= ~attr;
  1170.     if (fld->picture == _cf_globals.picture) {
  1171.     draw_field(fld);
  1172.     refresh();
  1173.     }
  1174. }
  1175.  
  1176. /*******************************************************************************
  1177.  *
  1178.  *        F L D _ T O U C H
  1179.  *        -----------------
  1180.  *
  1181.  * Description:
  1182.  *    Make field not modified.
  1183.  *
  1184.  ******************************************************************************/
  1185. void
  1186. fld_touch(struct field *fld)
  1187. {
  1188.     if (fld == NULL) fld = _cf_globals.field;
  1189.     if (fld == NULL) return;
  1190.     fld->modified = 0;
  1191. }
  1192.  
  1193.  
  1194. /*******************************************************************************
  1195.  *
  1196.  *        F I E L D
  1197.  *        ---------
  1198.  *
  1199.  * Description:
  1200.  *    Return pointer to field with name. Name works as printf.
  1201.  *
  1202.  ******************************************************************************/
  1203. struct field *
  1204. field(const char *fmt, ...)
  1205. {
  1206.     static char field_name[100];
  1207.     struct picture *pic;
  1208.     va_list arg;
  1209.     char *p;
  1210.     int i;
  1211.     
  1212.     va_start(arg, fmt);
  1213.     vsprintf(field_name, fmt, arg);
  1214.     va_end(arg);
  1215.     
  1216.     if (p = (char*)strchr(field_name, ':')) {
  1217.         *p++ = 0;
  1218.         pic = picture(field_name);
  1219.     }
  1220.     else {
  1221.         pic = _cf_globals.picture;
  1222.         p = field_name;
  1223.     }
  1224.     
  1225.     if (pic == NULL) return NULL;
  1226.     
  1227.     for(i = 0; i < pic->n_fields; i++) {
  1228.         if(strequ(p, pic->field[i].name) == 0) return &pic->field[i];
  1229.     }
  1230.  
  1231.     return NULL;
  1232. }
  1233.  
  1234. /*******************************************************************************
  1235.  *
  1236.  *        S T R E Q U
  1237.  *        -----------
  1238.  *
  1239.  * Description:
  1240.  *    Case insensitive strcmp.
  1241.  *
  1242.  ******************************************************************************/
  1243. int
  1244. strequ(const char *s1, const char *s2)
  1245. {
  1246.     while(*s1 && toupper(*s1) == toupper(*s2))
  1247.     s1++, s2++;
  1248.  
  1249.     return toupper(*s1) - toupper(*s2);
  1250. }
  1251.  
  1252.  
  1253. /*******************************************************************************
  1254.  *
  1255.  *        F L D _ L E F T
  1256.  *        ---------------
  1257.  *
  1258.  * Description:
  1259.  *    Return pointer to a field left of 'fld'.
  1260.  *
  1261.  ******************************************************************************/
  1262. struct field *
  1263. fld_left(const struct field *fld)
  1264. {
  1265.     int i;
  1266.     int min_dist = 1000000;
  1267.     int dist;
  1268.     struct field *found = NULL;
  1269.     
  1270.     if (fld == NULL) fld = _cf_globals.field;
  1271.     if (fld == NULL) fld = fld_first();
  1272.     if (fld == NULL) return NULL;
  1273.     
  1274.     for(i = 0; i < _cf_globals.picture->n_fields; i++)
  1275.     {
  1276.         if (fld != &_cf_globals.picture->field[i] &&
  1277.             _cf_globals.picture->field[i].pos.x < fld->pos.x)
  1278.         {
  1279.         if (_cf_globals.picture->field[i].flags & FLD_FORBIDDEN) continue;
  1280.  
  1281.         dist = (fld->pos.x - _cf_globals.picture->field[i].pos.x) << 9;
  1282.         dist += abs(fld->pos.y - _cf_globals.picture->field[i].pos.y);
  1283.         if (dist < min_dist)
  1284.         {
  1285.             min_dist = dist;
  1286.             found = &_cf_globals.picture->field[i];
  1287.         }
  1288.     }
  1289.     }
  1290.  
  1291.     return found;
  1292. }
  1293.  
  1294. /*******************************************************************************
  1295.  *
  1296.  *        F L D _ R I G H T
  1297.  *        -----------------
  1298.  *
  1299.  * Description:
  1300.  *    Return pointer to a field right of 'fld'.
  1301.  *
  1302.  ******************************************************************************/
  1303. struct field *
  1304. fld_right(const struct field *fld)
  1305. {
  1306.     int i;
  1307.     int min_dist = 1000000;
  1308.     int dist;
  1309.     struct field *found = NULL;
  1310.     
  1311.     if (fld == NULL) fld = _cf_globals.field;
  1312.     if (fld == NULL) fld = fld_first();
  1313.     if (fld == NULL) return NULL;
  1314.     
  1315.     for(i = 0; i < _cf_globals.picture->n_fields; i++)
  1316.     {
  1317.         if (fld != &_cf_globals.picture->field[i] &&
  1318.             _cf_globals.picture->field[i].pos.x > fld->pos.x)
  1319.         {
  1320.         if (_cf_globals.picture->field[i].flags & FLD_FORBIDDEN) continue;
  1321.  
  1322.         dist = (_cf_globals.picture->field[i].pos.x - fld->pos.x) << 9;
  1323.         dist += abs(fld->pos.y - _cf_globals.picture->field[i].pos.y);
  1324.         if (dist < min_dist)
  1325.         {
  1326.             min_dist = dist;
  1327.             found = &_cf_globals.picture->field[i];
  1328.         }
  1329.     }
  1330.     }
  1331.  
  1332.     return found;
  1333. }
  1334.  
  1335. /*******************************************************************************
  1336.  *
  1337.  *        F L D _ D O W N
  1338.  *        ---------------
  1339.  *
  1340.  * Description:
  1341.  *    Return a pointer to field below 'fld'.
  1342.  *
  1343.  ******************************************************************************/
  1344. struct field *
  1345. fld_down(const struct field *fld)
  1346. {
  1347.     int i;
  1348.     int min_dist = 1000000;
  1349.     int dist;
  1350.     struct field *found = NULL;
  1351.     
  1352.     if (fld == NULL) fld = _cf_globals.field;
  1353.     if (fld == NULL) fld = fld_first();
  1354.     if (fld == NULL) return NULL;
  1355.     
  1356.     for(i = 0; i < _cf_globals.picture->n_fields; i++)
  1357.     {
  1358.         if (fld != &_cf_globals.picture->field[i] &&
  1359.             _cf_globals.picture->field[i].pos.y > fld->pos.y)
  1360.         {
  1361.         if (_cf_globals.picture->field[i].flags & FLD_FORBIDDEN) continue;
  1362.  
  1363.         dist = (_cf_globals.picture->field[i].pos.y - fld->pos.y) << 9;
  1364.         dist += abs(_cf_globals.picture->field[i].pos.x - fld->pos.x);
  1365.         if (dist < min_dist)
  1366.         {
  1367.             min_dist = dist;
  1368.             found = &_cf_globals.picture->field[i];
  1369.         }
  1370.     }
  1371.     }
  1372.  
  1373.     return found;
  1374. }
  1375.  
  1376. /*******************************************************************************
  1377.  *
  1378.  *        F L D _ U P 
  1379.  *        -----------
  1380.  *
  1381.  * Description:
  1382.  *    Return pointer to field above 'fld'.
  1383.  *
  1384.  ******************************************************************************/
  1385. struct field *fld_up(const struct field *fld)
  1386. {
  1387.     int i;
  1388.     int min_dist = 1000000;
  1389.     int dist;
  1390.     struct field *found = NULL;
  1391.     
  1392.     if (fld == NULL) fld = _cf_globals.field;
  1393.     if (fld == NULL) fld = fld_first();
  1394.     if (fld == NULL) return NULL;
  1395.     
  1396.     for(i = 0; i < _cf_globals.picture->n_fields; i++)
  1397.     {
  1398.         if (fld != &_cf_globals.picture->field[i] &&
  1399.             _cf_globals.picture->field[i].pos.y < fld->pos.y)
  1400.         {
  1401.         if (_cf_globals.picture->field[i].flags & FLD_FORBIDDEN) continue;
  1402.  
  1403.         dist = (fld->pos.y - _cf_globals.picture->field[i].pos.y) << 9;
  1404.         dist += abs(_cf_globals.picture->field[i].pos.x - fld->pos.x);
  1405.         if (dist < min_dist)
  1406.         {
  1407.             min_dist = dist;
  1408.             found = &_cf_globals.picture->field[i];
  1409.         }
  1410.     }
  1411.     }
  1412.  
  1413.     return found;
  1414. }
  1415.  
  1416. /*******************************************************************************
  1417.  *
  1418.  *        F L D _ F I R S T
  1419.  *        -----------------
  1420.  *
  1421.  * Description:
  1422.  *    Find first field in picture.
  1423.  *
  1424.  ******************************************************************************/
  1425. struct field *
  1426. fld_first(void)
  1427. {
  1428.     int i;
  1429.     int min_dist = 1000000;
  1430.     int dist;
  1431.     struct field *found = NULL;
  1432.     
  1433.     for(i = 0; i < _cf_globals.picture->n_fields; i++)
  1434.     {
  1435.     if (_cf_globals.picture->field[i].flags & FLD_FORBIDDEN) continue;
  1436.  
  1437.     dist = _cf_globals.picture->field[i].pos.y << 9;
  1438.     dist += _cf_globals.picture->field[i].pos.x;
  1439.     if (dist < min_dist)
  1440.     {
  1441.         min_dist = dist;
  1442.         found = &_cf_globals.picture->field[i];
  1443.     }
  1444.     }
  1445.  
  1446.     return found;
  1447. }
  1448.  
  1449.  
  1450. /*******************************************************************************
  1451.  *
  1452.  *        F L D _ L A S T
  1453.  *        ---------------
  1454.  *
  1455.  * Description:
  1456.  *    Find last field in picture.
  1457.  *
  1458.  ******************************************************************************/
  1459. struct field *
  1460. fld_last(void)
  1461. {
  1462.     int i;
  1463.     int max_dist = -1;
  1464.     int dist;
  1465.     struct field *found = NULL;
  1466.  
  1467.     for(i = 0; i < _cf_globals.picture->n_fields; i++)
  1468.     {
  1469.     if (_cf_globals.picture->field[i].flags & FLD_FORBIDDEN) continue;
  1470.  
  1471.     dist = _cf_globals.picture->field[i].pos.y << 9;
  1472.     dist += _cf_globals.picture->field[i].pos.x;
  1473.     if (dist > max_dist)
  1474.     {
  1475.         max_dist = dist;
  1476.         found = &_cf_globals.picture->field[i];
  1477.     }
  1478.     }
  1479.  
  1480.     return found;
  1481. }
  1482.  
  1483. /*******************************************************************************
  1484.  *
  1485.  *        F L D _ N E X T
  1486.  *        ---------------
  1487.  *
  1488.  * Description:
  1489.  *    Find next field in picture.
  1490.  *
  1491.  ******************************************************************************/
  1492. struct field *
  1493. fld_next(const struct field *fld)
  1494. {
  1495.     int i;
  1496.     int min_dist = 1000000;
  1497.     int dist;
  1498.     struct field *found = NULL;
  1499.  
  1500.     if (fld == NULL) fld = _cf_globals.field;
  1501.     if (fld == NULL) fld = fld_first();
  1502.     if (fld == NULL) return NULL;
  1503.     
  1504.     for(i = 0; i < _cf_globals.picture->n_fields; i++)
  1505.     {
  1506.     if (_cf_globals.picture->field[i].flags & FLD_FORBIDDEN) continue;
  1507.  
  1508.     dist = (_cf_globals.picture->field[i].pos.y - fld->pos.y)<< 9;
  1509.     dist += _cf_globals.picture->field[i].pos.x - fld->pos.x;
  1510.     
  1511.     if (dist > 0 && dist < min_dist)
  1512.     {
  1513.         min_dist = dist;
  1514.         found = &_cf_globals.picture->field[i];
  1515.     }
  1516.     }
  1517.  
  1518.     return found;
  1519. }
  1520.  
  1521. /*******************************************************************************
  1522.  *
  1523.  *        F L D _ P R E V I O U S
  1524.  *        -----------------------
  1525.  *
  1526.  * Description:
  1527.  *    Find previoud field in picture.
  1528.  *
  1529.  ******************************************************************************/
  1530. struct field *fld_previous(const struct field *fld)
  1531. {
  1532.     int i;
  1533.     int min_dist = 1000000;
  1534.     int dist;
  1535.     struct field *found = NULL;
  1536.     
  1537.     if (fld == NULL) fld = _cf_globals.field;
  1538.     if (fld == NULL) fld = fld_first();
  1539.     if (fld == NULL) return NULL;
  1540.  
  1541.     for(i = 0; i < _cf_globals.picture->n_fields; i++)
  1542.     {
  1543.     if (_cf_globals.picture->field[i].flags & FLD_FORBIDDEN) continue;
  1544.  
  1545.     dist = (fld->pos.y - _cf_globals.picture->field[i].pos.y) << 9;
  1546.     dist += fld->pos.x - _cf_globals.picture->field[i].pos.x;
  1547.     
  1548.     if (dist > 0 && dist < min_dist)
  1549.     {
  1550.         min_dist = dist;
  1551.         found = &_cf_globals.picture->field[i];
  1552.     }
  1553.     }
  1554.  
  1555.     return found;
  1556. }
  1557.  
  1558. /*******************************************************************************
  1559.  *
  1560.  *        F L D _ I S E M P T Y
  1561.  *        ---------------------
  1562.  *
  1563.  * Description:
  1564.  *    Return true if field contains only space or nulls.
  1565.  *
  1566.  ******************************************************************************/
  1567. int
  1568. fld_isempty(const struct field *fld)
  1569. {
  1570.     int i;
  1571.     
  1572.     if (fld == NULL) fld = _cf_globals.field;
  1573.     if (fld == NULL) return TRUE;
  1574.     
  1575.     for(i = 0; i < fld->len; i++)
  1576.     {
  1577.         if (fld->data[i] == 0) return TRUE;
  1578.         if (!isspace(fld->data[i])) return FALSE;
  1579.     }
  1580.     return TRUE;
  1581. }
  1582.  
  1583. /*******************************************************************************
  1584.  *
  1585.  *        D R A W _ P I C T U R E
  1586.  *        -----------------------
  1587.  *
  1588.  * Description:
  1589.  *    Draw all literals and fields in a picture.
  1590.  *
  1591.  ******************************************************************************/
  1592. static int
  1593. draw_picture(struct picture *pic)
  1594. {
  1595.     int n;
  1596.     int r;
  1597.     int c;
  1598.     char space[400];
  1599.  
  1600.  
  1601.     if (pic == NULL) return FAIL;
  1602.     
  1603.     /*
  1604.      * Calculate blank it first.
  1605.      */
  1606.     memset(space, ' ', pic->width);
  1607.     space[pic->width] = 0;
  1608.      
  1609.     for(r = pic->y; r < pic->y + pic->height; r++) {
  1610.     move(r, pic->x);
  1611.     addstr(space);
  1612.     }    
  1613.     debug("$cleared window size");
  1614.  
  1615.     if (pic->flags & PIC_FRAME)
  1616.     {
  1617.     for(r = pic->y; r < pic->y + pic->height; r++) {
  1618.         move(r, pic->x);
  1619.         addch(ACS_VLINE);
  1620.         move(r, pic->x + pic->width - 1);
  1621.         addch(ACS_VLINE);
  1622.     }
  1623.  
  1624.     for(c = pic->x; c < pic->x + pic->width; c++) {
  1625.         move(pic->y, c);
  1626.         addch(ACS_HLINE);
  1627.         move(pic->y + pic->height - 1, c);
  1628.         addch(ACS_HLINE);
  1629.     }
  1630.     move(pic->y, pic->x); addch(ACS_ULCORNER);
  1631.     move(pic->y, pic->x + pic->width - 1); addch(ACS_URCORNER);
  1632.     move(pic->y + pic->height - 1, pic->x); addch(ACS_LLCORNER);
  1633.     move(pic->y + pic->height - 1, pic->x + pic->width - 1); addch(ACS_LRCORNER);
  1634.     }
  1635.     debug("$drawn frame");
  1636.  
  1637.     for(n = 0; n < pic->n_literals; n++)
  1638.     {
  1639.     move(pic->literal[n].pos.y + pic->y, pic->literal[n].pos.x + pic->x);
  1640.     addstr(pic->literal[n].value);
  1641.     }
  1642.     debug("$drawn %d literals", n);
  1643.     
  1644.     for(n = 0; n < pic->n_fields; n++)
  1645.     {
  1646.     draw_field(&pic->field[n]);
  1647.     }
  1648.     debug("$drawn %d fields", n);
  1649.  
  1650.     message_nr(NULL);
  1651.  
  1652.     return OK;
  1653. }
  1654.  
  1655. /******************************************************************************
  1656.  *
  1657.  *                        S I G C A T C H
  1658.  *                        ---------------
  1659.  * Description:
  1660.  *        Catches a signal, cleans up and exits.
  1661.  *
  1662.  *****************************************************************************/
  1663. #ifdef SIGNAL_INT
  1664. static int
  1665. #else
  1666. static void
  1667. #endif
  1668. sigcatch(int sig)
  1669. {
  1670.     cforms_end();
  1671.     exit(1);
  1672. #ifdef SIGNAL_INT
  1673.     return 0;    /* Just to shut up compiler */
  1674. #endif
  1675. }
  1676. /******************************************************************
  1677.  *        D R A W _ F I E L D
  1678.  *        -------------------
  1679.  * Decription:
  1680.  *    Write field to screen.
  1681.  *
  1682.  * Arguments:
  1683.  *    fld    - Pointer to field.
  1684.  *
  1685.  * Return:
  1686.  *    none
  1687.  *
  1688.  ******************************************************************/
  1689. static void
  1690. draw_field(struct field *fld)
  1691. {
  1692.     if (fld == NULL || fld->picture == NULL) {
  1693.     message("(internal error: field with unknown picture)");
  1694.     return;
  1695.     }
  1696.  
  1697.     if (fld->lvalue)
  1698.     {
  1699.     move(fld->pos.y + fld->picture->y,
  1700.          fld->pos.x - strlen(fld->lvalue) + fld->picture->x);
  1701.     addstr(fld->lvalue);
  1702.     }
  1703.  
  1704.     if (fld->rvalue) {
  1705.     move(fld->pos.y + fld->picture->y,
  1706.          fld->pos.x + fld->len + fld->picture->x);
  1707.     addstr(fld->rvalue);
  1708.     }
  1709.  
  1710.     if ((fld->flags & FLD_INVISIBLE) == 0)
  1711.     {
  1712.     if (fld->flags & FLD_HIGHLIGHT) {
  1713.         standout();
  1714.     }
  1715.  
  1716.     move(fld->pos.y + fld->picture->y, fld->pos.x + fld->picture->x);
  1717.     addstr(fld->data);
  1718.  
  1719.     if (fld->flags & FLD_HIGHLIGHT) {
  1720.         standend();
  1721.     }
  1722.     }
  1723. }
  1724.  
  1725. static void
  1726. debug(char *fmt, ...)
  1727. {
  1728.     static char init;    /* This is just a dummy address holder */
  1729.     static char *env = &init;
  1730.     static FILE *log;
  1731.     va_list arg;
  1732.     extern unsigned sleep(unsigned);
  1733.  
  1734.     /*
  1735.      * Get environment first time.
  1736.      */
  1737.     if (env == &init) {
  1738.     env = getenv("CFDEBUG");
  1739.  
  1740.     /*
  1741.      * Open file first time.
  1742.      */
  1743.     if (env) {
  1744.         if ((log = fopen("CForms.log", "w")) != NULL) {
  1745.         message("(started debug in CForms.log)");
  1746.         }
  1747.     }
  1748.     }
  1749.  
  1750.  
  1751.     /*
  1752.      * Print debug message if env set.
  1753.      */
  1754.     if (env && log)
  1755.     {
  1756.     /*
  1757.      * Write message.
  1758.      */
  1759.     if (fmt[0] == '$') {
  1760.         sleep (1);
  1761.         refresh();
  1762.         fmt++;
  1763.     }
  1764.     va_start(arg, fmt);
  1765.     vfprintf(log, fmt, arg);
  1766.     fprintf(log, "\n");
  1767.     fflush(log);
  1768.     va_end(arg);
  1769.     }
  1770. }
  1771. /******************************************************************
  1772.  *        M O V E _ T O _ F I E L D
  1773.  *        -------------------------
  1774.  * Description:
  1775.  *    Internal function to do the actual move of the field.
  1776.  *
  1777.  * Arguments:
  1778.  *    fld    - Pointer to field to move to.
  1779.  *
  1780.  ******************************************************************/
  1781. static void
  1782. move_to_field(struct field *fld)
  1783. {
  1784.     if (fld == NULL)
  1785.     {
  1786.     fld = _cf_globals.field;
  1787.     }
  1788.  
  1789.     /*
  1790.      * Repeat moving from and to fields while their event routines
  1791.      * calles the fld_move.
  1792.      */
  1793.     do
  1794.     {
  1795.     /*
  1796.      * First move from a field.
  1797.      */
  1798.     _cf_globals.move_field = NULL;
  1799.     if (_cf_globals.field) {
  1800.         raw_event(EVENT_EXIT, 0, 0);
  1801.         if (_cf_globals.move_field != NULL)
  1802.         {
  1803.         fld = _cf_globals.move_field;
  1804.         }
  1805.     }
  1806.  
  1807.     /*
  1808.      * Then move to a field.
  1809.      */
  1810.     _cf_globals.field = fld;
  1811.     _cf_globals.move_field = NULL;
  1812.     raw_event(EVENT_ENTRY, 0, 0);
  1813.     fld = _cf_globals.move_field;
  1814.  
  1815.     } while (_cf_globals.move_field != NULL);
  1816. }
  1817.